#ifndef GLGUI_H
#define GLGUI_H

#include "../core/vector2.h"
#include "../core/rect.h"
#include "../core/String.h"
#include "../core/Color.h"
#include "../core/foreach.h"
#include "../gl/GLFont.h"

#define GUI_LISTITEM_HEIGHT     30

#define GUI_ALIGN_CENTER    0x0
#define GUI_ALIGN_MIDDLE    0x0
#define GUI_ALIGN_LEFT      0x1
#define GUI_ALIGN_RIGHT     0x2
#define GUI_ALIGN_TOP       0x4
#define GUI_ALIGN_BOTTOM    0x8

class GLClient;

enum GLGuiType
{
    GUI_Desktop = 0,
    GUI_Frame,
    GUI_Button,
    GUI_Checkbox,
    GUI_Textbox,
    GUI_Label,
    GUI_HSlider,
    GUI_VSlider,
    GUI_Listbox,
    GUI_Menu,
    GUI_Unknown
};

class GLGuiControl
{
public:
    GLGuiControl(GLGuiControl* parent, GLGuiType t, int x, int y, int w, int h);
    virtual ~GLGuiControl();

    GLGuiControl* createControl(GLGuiType t, int x, int y, int w, int h);

    void drawControl(int status, bool in_focus);
    void drawControls(GLGuiControl* hov_ctl, GLGuiControl* clk_ctl, GLGuiControl* act_ctl);
    void beginClipping(const rectf& clip); //only for root control
    void endClipping();

    bool hitTest(int x, int y);
    GLGuiControl* pickTopControl(int x, int y);
    GLGuiControl* getControlById(int id);
    void swapControls(GLGuiControl* ctl1, GLGuiControl* ctl2);

    inline GLGuiType getType() const { return type; }
    inline GLGuiControl* getParent() { return parent; }

    inline const vector2i& getPosition() const { return position; }
    inline const vector2i& getSize() const { return size; }
    inline int getLeft() const  { return position.x; }
    inline int getTop() const   { return position.y; }
    inline int getWidth() const { return size.x; }
    inline int getHeight() const { return size.y; }
    inline const rectf& getBounds() const { return bounds; }

    void setPosition(int x, int y, int w=0, int h=0);
    void setSize(int w, int h);

    inline void setFont(GLFont* f) { font = f; }
    inline GLFont* getFont() const { return font; }

    inline GLClient* getClient() const { return client; }
    inline void setClient(GLClient* c) { client = c; }

    inline const String& getText() const { return text; }
    inline void setText(const String& s) { text = s; updateTextPos(); }
    inline void setTextAlign(int ta)     { textAlign = ta; updateTextPos(); }

    inline int getValue() const { return value; }
    inline void setValue(int v) { value = mClamp(v, 0, maxValue); }

    inline int getMaxValue() const { return maxValue; }
    inline void setMaxValue(int v) { maxValue = v; }

    inline int getId() const { return id; }
    inline void setId(int i) { id = i; }

    inline bool getVisible() const { return visible; }
    inline void setVisible(bool b) { visible = b; }

    inline bool getEnabled() const { return enabled; }
    inline void setEnabled(bool b) { enabled = b; }

    //list
    inline int getCurrentItem() const { return index; }
    inline void setCurrentItem(int i) { index = i; }
    inline int getItemsCount() const { return items.size(); }
    inline int getTopItem() const { return topItem; }
    inline int getHoverItem() const { return hoverIndex; }
    inline void setHoverItem(int t) { hoverIndex = t; }
    void addItem(const String& s);
    const String& getItem(int index) const;
    void clearItems();
    void setTopItem(int t, bool update_slider);
    int hitItem(int x, int y);
    void removeItem(int index);
    void fillItems(const char* itm_s);

    //image
    inline GLTexture* getImage() const   { return image; }
    inline void setImage(GLTexture* img) { image = img; }
    inline const vector2i& getImageSize() const { return imageSize; }
    inline void setImageSize(int w, int h) { imageSize.set(w, h); updateImagePos(); }
    //parsers
    static GLGuiType parseGuiType(const char* name);
    static int parseGuiAlign(const char* s);

private:
    void updateCtlPos();
    void updateTextPos();
    void updateListPos();
    void updateImagePos();

private:
    GLGuiType   type;
    int         id;
    vector2i    position;
    vector2i    size;
    rectf       bounds;
    bool        visible;
    bool        enabled;
    String      text;
    vector2f    textPos;
    int         textAlign;
    int         value;
    int         maxValue;
    GLFont*     font;
    GLTexture*  image;
    vector2i    imageSize;
    int         imageAlign;
    rectf       imagePos;
    //hierarhy
    GLGuiControl*   parent;
    GLGuiControl*   root;
    GLGuiControl*   front_ctl;
    GLClient*       client;
    std::list<GLGuiControl*> controls;
    //list box
    int index;
    int topItem;
    int hoverIndex;
    bool showSliders;
    std::vector<String> items;
};

#endif // GLGUI_H
